package demo.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;

import org.junit.Test;

/**
 * Created by zhangyanfei on 2017/9/15.
 *
 * @author zhangyanfei
 * @date 2017/09/15
 *
 * 流的操作类型分为两种：
 * Intermediate：
 * 一个流可以后面跟随零个或多个 intermediate 操作。
 * 其目的主要是打开流，做出某种程度的数据映射/过滤，然后返回一个新的流，交给下一个操作使用。
 * 这类操作都是惰性化的（lazy），就是说，仅仅调用到这类方法，并没有真正开始流的遍历。
 * Terminal：
 * 一个流只能有一个 terminal 操作，当这个操作执行后，流就被使用“光”了，无法再被操作。
 * 所以这必定是流的最后一个操作。
 * Terminal 操作的执行，才会真正开始流的遍历，并且会生成一个结果，或者一个 side effect。
 * Short-circuiting
 * 截取操作
 *
 * Intermediate：
 * map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
 * Terminal：
 * forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、
 * findAny、 iterator
 * Short-circuiting：
 * anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
 */
public class BuiderDemo {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        Person person = new Person();
        person.setAge(10);
        person.setName("Tom");
        personList.add(person);

        Person person2 = new Person();
        person2.setAge(11);
        person2.setName("Sam");
        personList.add(person2);

        Person person3 = new Person();
        person3.setAge(13);
        person3.setName("Tina");
        personList.add(person3);

        findFirst(personList);
    }

    /**
     * 排序
     */
    private static void Demo1() {
        int[] a = {7, 2, 3, 4, 2, 5, 1};

        List<Integer> result = Arrays.stream(a).boxed().sorted().collect(Collectors.toList());

        System.out.println(result);
    }

    /**
     * 变换
     */
    private static void mapDemo1(List<Person> personList) {
        List<Person> persons = personList.stream().map(person -> {
            person.setAge(person.getAge() + 1);
            return person;
        }).collect(Collectors.toList());

        persons.stream().forEach(person -> System.out.println(person.getAge() + ":" + person.getName()));
    }

    /**
     * 分组
     *
     * @param personList
     */
    private static void mapDemo2(List<Person> personList) {
        Map<Integer, List<Person>> map = personList.stream().map(person -> {
            person.setAge(person.getAge() + 1);
            return person;
        }).collect(Collectors.groupingBy(person -> (Integer)person.getAge(), Collectors.toList()));

        System.out.println(map.get(11));
        System.out.println(map.get(14));
    }

    /**
     * 转map
     */
    private static void toMap_C1(List<Person> personList) {
        Map<Integer, Person> personMap = personList.stream().collect(
            Collectors.toMap(Person::getId, Function.identity()));
    }

    /**
     * array -> list
     */
    private static List<Person> arrayToList(Person[] personArr) {
        return Arrays.stream(personArr).collect(Collectors.toList());
    }

    /**
     * list->array
     */
    private static Person[] listToArray(List<Person> personList) {
        return personList.toArray(new Person[0]);
    }

    /**
     * 数组和List互转
     *
     * @param list
     * @return
     */
    private static int[] listToArray_v2(List<Integer> list) {
        return list.stream().mapToInt(Integer::intValue).toArray();
    }

    private static List<Integer> arrayToList_v2(int[] array) {
        return Arrays.stream(array).boxed().collect(Collectors.toList());
    }

    @Test
    public void listToArray_test() {
        List<Person> personList = new ArrayList<Person>();
        Person person = new Person();
        person.setAge(10);
        person.setName("Tom");
        personList.add(person);

        Person person2 = new Person();
        person2.setAge(11);
        person2.setName("Sam");
        personList.add(person2);

        Person person3 = new Person();
        person3.setAge(13);
        person3.setName("Tina");
        personList.add(person3);
        Person[] personArr = listToArray(personList);
        List<Person> personList1 = arrayToList(personArr);
    }

    /**
     * filter
     */
    private static void filterDemo(List<Person> personList) {
        List<Person> result = personList.stream().filter((Person person) -> {
            return person.getAge() > 10;
        }).collect(Collectors.toList());

        System.out.println(result);
    }

    /**
     * 计算所有人年龄总和
     */
    private static void sum(List<Person> personList) {
        long total = personList.stream().mapToInt(x -> x.getAge()).sum();
        System.out.println(total);
    }

    /**
     * findFirst
     * findAny
     */
    private static void findFirst(List<Person> personList) {
        Person result = personList.stream()
            .filter(person -> person.getAge() > 10)
            .findAny().orElse(new Person());

        System.out.println(JSON.toJSONString(result));
    }

    /**
     * anyMatch
     * noneMatch
     * allMatch
     */
    private static void anyMatchTest(List<Person> personList) {
        boolean result = personList.stream().noneMatch(person -> person.getAge() > 10);
        System.out.println(result);
    }
}
